﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ObjectBakery.Tests.TestFactories;
using ObjectBakery.Helpers;
using ObjectBakery.Tests.TestDoubles;
using System.Data;
using System.Collections;

namespace ObjectBakery.Tests
{
    /// <summary>
    /// Summary description for SerializationHelperTests
    /// </summary>
    [TestClass]
    public class DataSyncHelperTests
    {
        public DataSyncHelperTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void CanSynchronizeObjectsOfSameType()
        {
            List<Product> products = new TestProductFactory().Build();

            DataSyncHelper synchHelper = new DataSyncHelper();

            Assert.IsFalse(products[0].ID.Equals(products[1].ID) && products[0].Name.Equals(products[1].Name));

            synchHelper.Sync(products[0], products[1]);

            Assert.IsTrue(products[0].ID.Equals(products[1].ID) && products[0].Name.Equals(products[1].Name));


        }

        [TestMethod]
        public void CanSynchronizeObjectsOfDifferentTypes()
        {
            Product product = new TestProductFactory().Build()[0];
            Asset asset = new TestAssetFactory().Build()[0];


            DataSyncHelper synchHelper = new DataSyncHelper();

            Assert.IsFalse(product.ID.Equals(asset.ID) && product.Name.Equals(asset.Name));

            synchHelper.Sync(product, asset);

            Assert.IsTrue(product.ID.Equals(asset.ID) && product.Name.Equals(asset.Name));
        }

        [TestMethod]
        public void CanSynchronizeAnObjectToADataRow()
        {
            Product product = new TestProductFactory().Build()[0];

            DataRow newRow = new TestTableFactory().BuildProducts().NewRow();

            DataSyncHelper synchHelper = new DataSyncHelper();

            synchHelper.Sync(product, newRow);

            Assert.IsTrue(product.ID.Equals(newRow["ID"]) && product.Name.Equals(newRow["Name"]));
        }

        [TestMethod]
        public void CanSynchronizeADataRowToAnObject()
        {
            Product product = new TestProductFactory().Build()[0];

            DataRow existingRow = new TestTableFactory().BuildProducts().Rows[0];

            //check that they are different
            Assert.IsFalse(product.ID.Equals(existingRow["ID"]) && product.Name.Equals(existingRow["Name"]));

            DataSyncHelper synchHelper = new DataSyncHelper();

            synchHelper.Sync(existingRow, product);

            //ensure they are the same
            Assert.IsTrue(product.ID.Equals(existingRow["ID"]) && product.Name.Equals(existingRow["Name"]));
        }


        [TestMethod]
        public void CanSynchronizeAnIDictionaryToAnObject()
        {
            Product product = new TestProductFactory().Build()[0];

            IDictionary dictionary = new TestDictionaryFactory().Build();

            //check that they are different
            Assert.IsFalse(product.ID.Equals(dictionary["ID"]) && product.Name.Equals(dictionary["Name"]));

            DataSyncHelper synchHelper = new DataSyncHelper();

            synchHelper.Sync(dictionary, product);

            //ensure they are the same
            Assert.IsTrue(product.ID.Equals(dictionary["ID"]) && product.Name.Equals(dictionary["Name"]));
        }

        [TestMethod]
        public void CanSynchronizeAnObjectToAnIDictionary()
        {
            Product product = new TestProductFactory().Build()[0];

            IDictionary dictionary = new TestDictionaryFactory().Build();

            //check that they are different
            Assert.IsFalse(product.ID.Equals(dictionary["ID"]) && product.Name.Equals(dictionary["Name"]));

            DataSyncHelper synchHelper = new DataSyncHelper();

            synchHelper.Sync(product, dictionary);

            //ensure they are the same
            Assert.IsTrue(product.ID.Equals(dictionary["ID"]) && product.Name.Equals(dictionary["Name"]));
        }

        [TestMethod]
        public void CanSynchronizeAnIDictionaryToADataRow()
        {
            DataRow existingRow = new TestTableFactory().BuildProducts().Rows[0];

            IDictionary dictionary = new TestDictionaryFactory().Build();

            //check that they are different
            Assert.IsFalse(dictionary["ID"].Equals(existingRow["ID"]) && dictionary["Name"].Equals(existingRow["Name"]));

            DataSyncHelper synchHelper = new DataSyncHelper();

            synchHelper.Sync(dictionary, existingRow);

            //ensure they are the same
            Assert.IsTrue(dictionary["ID"].Equals(existingRow["ID"]) && dictionary["Name"].Equals(existingRow["Name"]));
        }

        [TestMethod]
        public void CanSynchronizeADataRowToAnIDictionary()
        {
            DataRow existingRow = new TestTableFactory().BuildProducts().Rows[0];

            IDictionary dictionary = new TestDictionaryFactory().Build();

            //check that they are different
            Assert.IsFalse(dictionary["ID"].Equals(existingRow["ID"]) && dictionary["Name"].Equals(existingRow["Name"]));

            DataSyncHelper synchHelper = new DataSyncHelper();

            synchHelper.Sync(existingRow, dictionary);

            //ensure they are the same
            Assert.IsTrue(dictionary["ID"].Equals(existingRow["ID"]) && dictionary["Name"].Equals(existingRow["Name"]));
        }

        [TestMethod]
        public void UseSyncToConvertDataTableToIDictionaryAndBack()
        {
            DataTable productsDataTable = new TestTableFactory().BuildProducts();

            List<IDictionary> productDictionaries = new List<IDictionary>();

            DataSyncHelper dataSyncHelper = new DataSyncHelper();

            productsDataTable.Rows.Cast<DataRow>().ToList().ForEach(row =>
                {
                    IDictionary productDictionary = new Hashtable();
                    dataSyncHelper.Sync(row, productDictionary);
                    productDictionaries.Add(productDictionary);                       
                });

            //assertions
            for (int j = 0; j < productsDataTable.Rows.Count; j++)
            {
                DataRow pRow = productsDataTable.Rows[j];
                IDictionary dict = productDictionaries[j];
              
                //compare each value
                for (int i = 0; i < productsDataTable.Columns.Count; i++)
                {
                    DataColumn column = productsDataTable.Columns[i];

                    //object equivalence does not hold here.  
                    //using ToString() since I haven't overriden Equals().
                    Assert.IsTrue(pRow.ItemArray[i].ToString() == dict[column.ColumnName].ToString());
                }
            }

        }
    }
}
